﻿/*
Copyright (C) 2009  Tomasz Chrzanowski

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/

using System;
using System.Collections.Generic;
using System.Text;


namespace Com.TomCdc.ChangeDataCapture
{
    /// <summary>
    /// Represents the column of tracked source database table.
    /// </summary>
    public class SourceColumn
    {
        /// <summary>
        /// The name of the column the object represents.
        /// </summary>
        private string _columnName;

        /// <summary>
        /// The ordinal position of the column in tha table.
        /// </summary>
        private int _ordinalPosition;

        /// <summary>
        /// The sql data type of the column.
        /// </summary>
        private string _dataType;

        /// <summary>
        /// The maximal length of the column.
        /// </summary>
        private int _maxLength;

        /// <summary>
        /// Indicates if the column is currently tracked.
        /// </summary>
        private bool _isTracked;

        /// <summary>
        /// Indicates of the column should be tracked.
        /// </summary>
        private bool _activateTracking;

        /// <summary>
        /// Indicates if the columns type is one of not trackable,
        /// defined in <see cref="CommonInfo.NotTrackableTypes"/>.
        /// </summary>
        private bool _isDisabled;

        /// <summary>
        /// Indicates if the column is primary key of the table. If no primary key in the table but this column
        /// contains unique values (uniqe constraint), is set to true.
        /// </summary>
        private bool _isPrimaryKey;

        /// <summary>
        /// The ordinal position of a source column from the storage database. It doesn't change when source table schema changes.
        /// </summary>
        private int _storeSrcColOrdinal;

        /// <summary>
        /// Initializes an instance of <see cref="SourceColumn"/> class with the name of column.
        /// </summary>
        /// <param name="columnName">The column name.</param>
        /// <param name="dataType">The column data type.</param>
        /// <param name="ordinalPosition">The ordinal position of the column. Position must be greater than 0.</param>
        public SourceColumn(string columnName, string dataType, int ordinalPosition)
        {
            if (string.IsNullOrEmpty(columnName))
            {
                throw new ArgumentException("The columnName argument must not be empty or null.");
            }

            if (string.IsNullOrEmpty(dataType))
            {
                throw new ArgumentException("The dataType argument must not be empty or null.");
            }

            if (ordinalPosition <= 0)
            {
                throw new ArgumentOutOfRangeException("The ordinalPosition argument must be grater then 0.");
            }

            _ordinalPosition = ordinalPosition;

            _dataType = dataType;
            if (CommonHelper.NotTrackableTypes.Contains(dataType))
            {
                _isDisabled = true;
            }

            _columnName = columnName;
        }

        /// <summary>
        /// Gets or sets a value indicating whether the column is a primary key. The property set to true,
        /// when no primary key in the table, but this column contains unique values (uniqe constraint).
        /// </summary>
        public bool IsPrimaryKey
        {
            get
            {
                return _isPrimaryKey;
            }

            set
            {
                _isPrimaryKey = value;
            }
        }

        /// <summary>
        /// Gets the name of a column.
        /// </summary>
        public string ColumnName
        {
            get
            {
                return _columnName;
            }
        }

        /// <summary>
        /// Gets the ordinal position of the column. The position is 1 based.
        /// </summary>
        public int OrdinalPosition
        {
            get
            {
                return _ordinalPosition;
            }
        }

        /// <summary>
        /// Gets sql data type of the column.
        /// </summary>
        public string DataType
        {
            get
            {
                return _dataType;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating maximal length of the column.
        /// </summary>
        public int MaxLength
        {
            get
            {
                return _maxLength;
            }

            set
            {
                if (value < 0)
                {
                    throw new ArgumentOutOfRangeException("The maxlength must be grater then or equal 0.");
                }
                _maxLength = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating wheather the column is currently tracked.
        /// True if currently tracked, otherwise false.
        /// </summary>
        public bool IsTracked
        {
            get
            {
                return _isTracked;
            }

            set
            {
                _isTracked = value;

                // if currently tracked, activate tracking to install as well
                _activateTracking = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating wheather the column will be tracked.
        /// True if the column should be tracked.
        /// </summary>
        /// <exception cref="ArgumentException">When the column is disabled and the true 
        /// status is assigned.</exception>
        public bool ActivateTracking
        {
            get
            {
                return _activateTracking;
            }

            set
            {
                if (_isDisabled && value)
                {
                    throw new ArgumentException("The tracking activation can not be set for disabled column.");
                }
                _activateTracking = value;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the column is disabled.
        /// True if disabled, it means the column sql type is one of 
        /// defined in <see cref="CommonInfo.NotTrackableTypes"/>.
        /// </summary>
        public bool IsDisabled
        {
            get
            {
                return _isDisabled;
            }
        }

        /// <summary>
        /// The ordinal position of a source column from the storage database. It doesn't change when source table schema changed.
        /// </summary>
        /// <exception cref="InvalidOperationException">Thrown when source column ordinal position is not initialized. To do so, 
        /// <see cref="SourceSchemaFactory.CreateAllSourceTables(true)"/> must be used.</exception>
        public int StoreSourceColumnOrdinal
        {
            get
            {
                if (_storeSrcColOrdinal <= 0)
                {
                    throw new InvalidOperationException("The store database source column ordinal position not initialized.");
                }

                return _storeSrcColOrdinal;
            }

            set
            {
                _storeSrcColOrdinal = value;
            }            
        }

    }
}
